import { combineResolvers } from 'graphql-resolvers'
import { pageModel } from '../../lib/helper'
import auth from '../../middlewares/auth'
import { documentLoader } from '../document/dataloaders'
import { userLoader } from '../user/dataloaders'
import { groupLoader } from '../group/dataloaders'
import dayjs from 'dayjs'
import fdb from '../../lib/fdb'
import CONFIG from '../../config'
import axios from 'axios'

module.exports = {
  Query: {
    task: async (root, { id }, { models: { Task } }) => {
      const result = await Task.findById(id)
      return result
    },
    documentTasks: combineResolvers(
      auth,
      async (
        root,
        { documentId, pageIndex, pageSize },
        { services: { $task }, user }
      ) => {
        let userId = user.id
        const result = await $task.findAllDocumentTasks(
          documentId,
          userId,
          pageIndex,
          pageSize
        )
        let t = pageModel(result, pageIndex, pageSize)
        return t
      }
    ),
    taskGetAllByIds: combineResolvers(
      auth,
      async (
        root,
        { taskIds },
        { models: { Task }, user }
      ) => {
        let tasks = await Task.findAll({
          where: {
            id: taskIds
          }
        })
        return tasks
      }
    ),
    assignment: combineResolvers(
      async (
        root,
        { id },
        { models: { Task }, user }
      ) => {
        let task = await Task.findOne({
          where: {
            type: 'exercise',
            documentId: id
          }
        })
        return task
      }
    ),
    taskGetMyCreates: combineResolvers(
      auth,
      async (
        root,
        { filter: {type = 'published', params = null}, currentPage = 1, pageSize = 20 },
        { models: { Task }, user }
      ) => {
        let where = {ownerId: user.id}
        let order = ['createdAt', 'desc']
        if (type == 'published') {
          where.isPublished = 1
        } else if (type == 'unpublished') {
          order = ['prePublishAt', 'asc']
          where.isPublished = 0
        }

        let rs = await Task.findAndCountAll({
          where,
          raw: true,
          offset: (currentPage - 1) * pageSize,
          limit: pageSize,
          order: [order]
        })

        let page = {currentPage, pageSize, totalCount: rs.count, totalPages: Math.ceil(rs.count / pageSize)}
        let rows = rs.rows
        if (rows.length) {
          let agids = rs.rows.map(n => {
            return n.documentId + '_' + n.groupId
          })
          let apiUrl = `${CONFIG.app.contentServerApi}/v1/assignments/${agids.join(',')}/submissions/count`
          let res = await axios({
            method: 'get',
            url: apiUrl,
            headers: {
              'Authorization': 'Bearer 1EB39DDA-CA30-458F-9E13-BDE9CE2B5A12'
            }
          })
          let kvAgidCount = {}
          if (res.data.countedItems) {
            res.data.countedItems.forEach(n => {
              kvAgidCount[`${n.assignmentId}_${n.classId}`] = n.totalSubmitted
            })
          }
          rows = rs.rows.map(n => {
            n.totalSubmitted = 0
            if (n.type === 'exercise') {
              n.totalSubmitted = kvAgidCount[`${n.documentId}_${n.groupId}`] || 0
            }
            return n
          })
        }
        return {
          page,
          rows
        }
      }
    ),
    taskGetMyUnreadCount: combineResolvers(
      auth,
      async (
        root,
        data,
        { models: { Task }, user }
      ) => {
        let t = await fdb.findOne({
          tbl: 'tasks',
          attrs: [
            'sum(unreadCount) as totalUnreadCount'
          ],
          where: [
            'ownerId=' + user.id
          ]
        })
        if (!t) return 0
        if (!t.totalUnreadCount) return 0
        return t.totalUnreadCount
      }
    )
  },
  Mutation: {
    findOrCreateTask: combineResolvers(
      auth,
      async (root, { documentId, groupId }, { services: { $task }, user }) => {
        let userId = user.id
        console.info(
          `create or find task with documentId:${documentId} userId:${userId} groupId:${groupId}`
        )
        return await $task.findOrCreate({documentId, userId, groupId})
      }
    ),
    urgeTask: combineResolvers(
      auth,
      async (root, { taskId }, { services: { $task }, user }) => {
        let userId = user.id
        console.info('urge task by sending notifications:', taskId)
        return await $task.urge(taskId, userId)
      }
    ),
    taskModify: combineResolvers(
      auth,
      async (
        root,
        { taskId, endAt, prePublishAt },
        { models: { Task }, user }
      ) => {
        let task = await Task.update({
          expireAt: endAt,
          prePublishAt
        }, {
          where: {
            id: taskId,
            ownerId: user.id
          }
        })
        return await Task.findById(taskId)
      }
    )
    // removeTask: combineResolvers(
    //   auth,
    //   async (root, { taskId }, { services: { $task }, user }) => {
    //     let userId = user.id
    //     console.info('delete task:', taskId)
    //     return await $task.remove(taskId, userId)
    //   }
    // )
  },
  Task: {
    creator: (
      { ownerId },
      data,
      { models: { UserGroup, User }, dataloaders: { userLoader } }
    ) => {
      return userLoader.load(ownerId)
    },
    document: (
      { versionId },
      data,
      { models: { Document }, dataloaders: { documentLoader } }
    ) => {
      return documentLoader.load(versionId)
    },
    group: (
      { groupId },
      data,
      { models: { Group }, dataloaders: { groupLoader } }
    ) => {
      return groupLoader.load(groupId)
    },
    user: (
      { userId },
      data,
      { models: { UserGroup, User }, dataloaders: { userLoader } }
    ) => {
      return userLoader.load(userId)
    },
    progresses: ({ id }, data, { dataloaders: { progressLoaderByTask } }) => {
      let t = progressLoaderByTask.load(id)
      return t
    },
    finishCount: (
      { id },
      data,
      { dataloaders: { finishCountLoaderByTask } }
    ) => {
      return finishCountLoaderByTask.load(id)
    },
    expireAtISO: (
      { expireAt },
      data
    ) => {
      if (!expireAt) return ''
      return dayjs(expireAt).toISOString()
    },
    unreadCount: (
      { id },
      data,
      { dataloaders: { unreadCountLoaderByTask } }
    ) => {
      return unreadCountLoaderByTask.load(id)
    },
    isExpired: ({ expireAt }, data) => {
      if (!expireAt) return false
      let flag = dayjs().isAfter(dayjs(expireAt))
      return flag
    }
  }
}
